/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.code.config;

import vip.dexian.code.generator.Config;
import vip.dexian.common.CommonAttributes;
import vip.dexian.common.utils.LocalDateTimeUtils;
import vip.dexian.core.base.bean.BaseLogEntity;
import vip.dexian.core.base.bean.OrderEntity;
import vip.dexian.core.base.bean.TreeEntity;
import vip.dexian.core.base.bean.UniqueEntity;
import vip.dexian.core.base.bean.UniqueOrderEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.Comment;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 模型Map，存放需要替换的内容数据
 *
 * @author 挺好的 2023年06月06日 13:12
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode (callSuper = false)
public class ModelMap {

    private static AnnotationUtils annotationUtils;

    /**
     * class全名
     */
    private String className;

    /**
     * class简单名称
     */
    private String simpleClassName;

    /**
     * 首字符小写的class名称
     */
    private String unCapitalizeClassName;

    /**
     * 转下划线
     */
    private String underlineName;

    /**
     * class 对象
     */
    private Class entityClass;

    /**
     * 当前时间
     */
    private String now;

    /**
     * 作者
     */
    private String author;

    /**
     * 实体类功能描述（表注释）
     */
    private String entityComment;

    /**
     * 表的名字
     */
    private String tableName;

    /**
     * 该类的属性
     */
    private List <CustomField> fields;

    /**
     * 索引
     */
    private List <IndexField> indexFields;

    /**
     * $符号
     */
    private String dollar;

    /**
     * 所有属性设置完毕以后，调用初始化方法
     *
     * @return
     */
    public ModelMap afterPropertiesSet () {
        if (this.entityClass == null) {
            throw new IllegalArgumentException("entity class not null");
        }

        annotationUtils = AnnotationUtils.getInstance(this.entityClass);

        this.initClass();
        this.initDateAndAuthor();
        this.initTableInfo();
        this.initFields();
        this.initSql();


        return this;
    }

    /**
     * 初始化表的注释信息（实体类的注释）
     */
    private void initTableInfo () {
        this.tableName = annotationUtils.getTableName();
    }

    /**
     * 初始化该类的域
     */
    private void initFields () {

        Field[] fields = this.entityClass.getDeclaredFields();

        this.fields = new ArrayList <>();

        for (Field field : fields) {

            if (field.getAnnotation(Comment.class) == null) {
                continue;
            }
            CustomField customField = new CustomField(field);
            this.fields.add(customField);
        }
    }

    /**
     * 初始化对象的class信息
     */
    private void initClass () {
        this.className             = this.entityClass.getName();
        this.simpleClassName       = this.entityClass.getSimpleName();
        this.unCapitalizeClassName = StringUtils.uncapitalize(this.simpleClassName);
        this.underlineName         = humpToUnderline(this.unCapitalizeClassName);
        this.dollar                = "$";
    }

    /**
     * 初始化日期和作者
     */
    private void initDateAndAuthor () {
        this.now    = LocalDateTimeUtils.format(CommonAttributes.DatePattern.DATE_TIME_4, LocalDateTime.now());
        this.author = Config.AUTHOR;
    }

    /**
     * 初始化sql语句，注意如果是Many to Many，要生成中间表
     */
    private void initSql () {
        Field[] fields = this.entityClass.getDeclaredFields();

        this.fields = new ArrayList <>();

        this.indexFields = AnnotationUtils.getInstance(this.entityClass).getIndex();

        for (Field field : fields) {
            CustomField customField = new CustomField(field, false);

            if (StringUtils.isEmpty(customField.getName())) {
                continue;
            }

            this.fields.add(customField);

            if (customField.isUnique()) {
                IndexField indexField = new IndexField();
                indexField.setName(customField.getColumnName());
                indexField.setIsUnique(true);

                List <String> columns = new ArrayList <>();
                columns.add(customField.getColumnName());
                indexField.setColumns(columns);
                this.indexFields.add(indexField);
            }
        }

        Class superClass = this.entityClass.getSuperclass();
        if (superClass == OrderEntity.class || superClass == UniqueOrderEntity.class) {
            CustomField customField = new CustomField();
            customField.setJavaType("Integer");
            customField.setComment("排序");
            customField.setJdbcType("INTEGER(8) unsigned");
            customField.setName("order");
            customField.setColumnName("orders");
            customField.setNullable(false);
            customField.setIsEntity(false);
            this.fields.add(customField);
        }

        if (superClass == UniqueEntity.class || superClass == UniqueOrderEntity.class) {
            CustomField customField = new CustomField();
            customField.setComment("唯一索引，用于逻辑删除");
            customField.setJdbcType("BIGINT(20) unsigned");
            customField.setName("uniqueTimestamp");
            customField.setColumnName("unique_timestamp");
            customField.setNullable(false);
            customField.setJavaType("Long");
            customField.setIsEntity(false);
            this.fields.add(customField);
        }

        if (superClass == BaseLogEntity.class) {

            CustomField customField = new CustomField();
            customField.setComment("IP");
            customField.setJdbcType("BIGINT(20) unsigned");
            customField.setName("ip");
            customField.setColumnName("ip");
            customField.setNullable(true);
            customField.setJavaType("Long");
            customField.setIsEntity(false);
            this.fields.add(customField);

            CustomField f1 = new CustomField();
            f1.setJavaType("String");
            f1.setComment("浏览器");
            f1.setJdbcType("VARCHAR(100)");
            f1.setName("browser");
            f1.setColumnName("browser");
            f1.setNullable(true);
            f1.setIsEntity(false);
            this.fields.add(f1);

            CustomField f2 = new CustomField();
            f2.setJavaType("String");
            f2.setComment("浏览器版本");
            f2.setJdbcType("VARCHAR(50)");
            f2.setName("browserVersion");
            f2.setColumnName("browser_version");
            f2.setNullable(true);
            f2.setIsEntity(false);
            this.fields.add(f2);

            CustomField f3 = new CustomField();
            f3.setJavaType("String");
            f3.setComment("操作系统");
            f3.setJdbcType("VARCHAR(50)");
            f3.setName("osName");
            f3.setColumnName("os_name");
            f3.setNullable(true);
            f3.setIsEntity(false);
            this.fields.add(f3);

            CustomField f33 = new CustomField();
            f33.setJavaType("String");
            f33.setComment("设备类型");
            f33.setJdbcType("VARCHAR(100)");
            f33.setName("deviceType");
            f33.setColumnName("device_type");
            f33.setNullable(true);
            f33.setIsEntity(false);
            this.fields.add(f33);

        }

        if (superClass == TreeEntity.class) {

            CustomField customField4 = new CustomField();
            customField4.setJavaType("Long");
            customField4.setComment("上级ID");
            customField4.setJdbcType("BIGINT(20) unsigned");
            customField4.setName("parentId");
            customField4.setColumnName("parent_id");
            customField4.setNullable(false);
            customField4.setIsEntity(false);
            this.fields.add(customField4);

            CustomField customField = new CustomField();
            customField.setComment("上下级路径");
            customField.setJdbcType("VARCHAR(255)");
            customField.setName("treePath");
            customField.setColumnName("tree_path");
            customField.setNullable(false);
            customField.setJavaType("String");
            customField.setIsEntity(false);
            this.fields.add(customField);

            CustomField customField2 = new CustomField();
            customField2.setComment("等级");
            customField2.setJdbcType("INTEGER(11) unsigned");
            customField2.setName("grade");
            customField2.setColumnName("grade");
            customField2.setNullable(false);
            customField2.setJavaType("Integer");
            customField2.setIsEntity(false);
            this.fields.add(customField2);

            CustomField customField3 = new CustomField();
            customField3.setJavaType("Integer");
            customField3.setComment("排序");
            customField3.setJdbcType("INTEGER(11) unsigned");
            customField3.setName("order");
            customField3.setColumnName("orders");
            customField3.setNullable(false);
            customField3.setIsEntity(false);
            this.fields.add(customField3);

        }

        //        if (superClass == BaseLocationDeviceEntity.class) {
        //
        //            CustomField f1 = new CustomField();
        //            f1.setJavaType("String");
        //            f1.setComment("城市编码");
        //            f1.setJdbcType("VARCHAR(10)");
        //            f1.setName("cityCode");
        //            f1.setColumnName("city_code");
        //            f1.setNullable(true);
        //            this.fields.add(f1);
        //
        //            CustomField f2 = new CustomField();
        //            f2.setJavaType("String");
        //            f2.setComment("区域编码");
        //            f2.setJdbcType("VARCHAR(50)");
        //            f2.setName("adCode");
        //            f2.setColumnName("ad_code");
        //            f2.setNullable(true);
        //            this.fields.add(f2);
        //
        //            CustomField f3 = new CustomField();
        //            f3.setJavaType("String");
        //            f3.setComment("城市名称");
        //            f3.setJdbcType("VARCHAR(50)");
        //            f3.setName("cityName");
        //            f3.setColumnName("city_name");
        //            f3.setNullable(true);
        //            this.fields.add(f3);
        //
        //            CustomField f33 = new CustomField();
        //            f33.setJavaType("String");
        //            f33.setComment("区/县名称");
        //            f33.setJdbcType("VARCHAR(50)");
        //            f33.setName("districtName");
        //            f33.setColumnName("district_name");
        //            f33.setNullable(true);
        //            this.fields.add(f33);
        //
        //            CustomField f4 = new CustomField();
        //            f4.setJavaType("Double");
        //            f4.setComment("经度");
        //            f4.setJdbcType("DOUBLE(12,6)");
        //            f4.setName("longitude");
        //            f4.setColumnName("longitude");
        //            f4.setNullable(true);
        //            this.fields.add(f4);
        //
        //            CustomField f5 = new CustomField();
        //            f5.setJavaType("Double");
        //            f5.setComment("纬度");
        //            f5.setJdbcType("DOUBLE(12,6)");
        //            f5.setName("latitude");
        //            f5.setColumnName("latitude");
        //            f5.setNullable(true);
        //            this.fields.add(f5);
        //
        //            CustomField f6 = new CustomField();
        //            f6.setJavaType("String");
        //            f6.setComment("地理位置");
        //            f6.setJdbcType("VARCHAR(200)");
        //            f6.setName("location");
        //            f6.setColumnName("location");
        //            f6.setNullable(true);
        //            this.fields.add(f6);
        //
        //            CustomField f7 = new CustomField();
        //            f7.setJavaType("PlatformEnum");
        //            f7.setComment("来源平台");
        //            f7.setJdbcType("TINYINT(1)");
        //            f7.setName("platform");
        //            f7.setColumnName("platform");
        //            f7.setNullable(false);
        //            this.fields.add(f7);
        //
        //            CustomField f8 = new CustomField();
        //            f8.setJavaType("String");
        //            f8.setComment("设备品牌");
        //            f8.setJdbcType("VARCHAR(50)");
        //            f8.setName("brand");
        //            f8.setColumnName("brand");
        //            f8.setNullable(false);
        //            this.fields.add(f8);
        //
        //            CustomField f9 = new CustomField();
        //            f9.setJavaType("String");
        //            f9.setComment("设备唯一ID");
        //            f9.setJdbcType("VARCHAR(100)");
        //            f9.setName("uniqueId");
        //            f9.setColumnName("unique_id");
        //            f9.setNullable(false);
        //            this.fields.add(f9);
        //
        //            CustomField f10 = new CustomField();
        //            f10.setJavaType("String");
        //            f10.setComment("设备型号");
        //            f10.setJdbcType("VARCHAR(100)");
        //            f10.setName("mode");
        //            f10.setColumnName("mode");
        //            f10.setNullable(false);
        //            this.fields.add(f10);
        //
        //            CustomField f11 = new CustomField();
        //            f11.setJavaType("String");
        //            f11.setComment("操作系统");
        //            f11.setJdbcType("VARCHAR(100)");
        //            f11.setName("os");
        //            f11.setColumnName("os");
        //            f11.setNullable(false);
        //            this.fields.add(f11);
        //
        //            CustomField f12 = new CustomField();
        //            f12.setJavaType("String");
        //            f12.setComment("操作系统版本");
        //            f12.setJdbcType("VARCHAR(100)");
        //            f12.setName("osVersion");
        //            f12.setColumnName("os_version");
        //            f12.setNullable(false);
        //            this.fields.add(f12);
        //
        //            CustomField f13 = new CustomField();
        //            f13.setJavaType("String");
        //            f13.setComment("ip");
        //            f13.setJdbcType("VARCHAR(50)");
        //            f13.setName("ip");
        //            f13.setColumnName("ip");
        //            f13.setNullable(false);
        //            this.fields.add(f13);
        //
        //        }

    }

    public static String humpToUnderline (String humpName) {
        //截取下划线分成数组，

        char[] charArray = humpName.toCharArray();

        StringBuffer buffer = new StringBuffer();

        //处理字符串

        for (int i = 0, l = charArray.length; i < l; i++) {
            if (charArray[i] >= 65 && charArray[i] <= 90) {
                buffer.append("_").append(charArray[i] += 32);

            } else {
                buffer.append(charArray[i]);

            }

        }

        return buffer.toString();
    }
}
